Coverage Report

Created: 2025-11-24 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bag/api/bag_georefmetadatalayerdescriptor.cpp
Line
Count
Source
1
2
#include "bag_dataset.h"
3
#include "bag_georefmetadatalayerdescriptor.h"
4
#include "bag_metadataprofiles.h"
5
#include "bag_hdfhelper.h"
6
#include "bag_private.h"
7
#include "bag_valuetable.h"
8
9
#include <iostream>
10
#include <array>
11
#include <H5Cpp.h>
12
13
14
namespace BAG {
15
16
//! Constructor.
17
/*!
18
\param dataset
19
    The BAG Dataset this layer belongs to.
20
\param name
21
    The name of the simple layer this layer has metadata for.
22
\param keyType
23
    The type of the key.
24
    Must be DT_UINT8, DT_UINT16, DT_UINT32, or DT_UINT64.
25
\param definition
26
    The list of fields describing a record/value.
27
\param chunkSize
28
    The chunk size the HDF5 DataSet will use.
29
\param compressionLevel
30
    The compression level the HDF5 DataSet will use.
31
*/
32
GeorefMetadataLayerDescriptor::GeorefMetadataLayerDescriptor(
33
        Dataset& dataset,
34
        const std::string& name,
35
        GeorefMetadataProfile profile,
36
        DataType keyType,
37
        RecordDefinition definition,
38
        uint64_t chunkSize,
39
        int compressionLevel)
40
52
    : LayerDescriptor(dataset.getNextId(), GEOREF_METADATA_PATH + name, name,
41
52
                      Georef_Metadata, chunkSize, compressionLevel)
42
52
    , m_pBagDataset(dataset.shared_from_this())
43
52
    , m_profile(profile)
44
52
    , m_keyType(keyType)
45
52
    , m_elementSize(Layer::getElementSize(keyType))
46
52
    , m_definition(std::move(definition))
47
52
{
48
52
}
49
50
//! Create a georeferenced metadata layer descriptor.
51
/*!
52
\param dataset
53
    The BAG Dataset this layer belongs to.
54
\param name
55
    The name of the simple layer this layer has metadata for.
56
\param keyType
57
    The type of the key.
58
    Must be DT_UINT8, DT_UINT16, DT_UINT32, or DT_UINT64.
59
\param definition
60
    The list of fields describing a record/value this layer contains for each node.
61
\param chunkSize
62
    The chunk size the HDF5 DataSet will use.
63
\param compressionLevel
64
    The compression level the HDF5 DataSet will use.
65
66
\return
67
    The new georeferenced metadata layer descriptor.
68
*/
69
std::shared_ptr<GeorefMetadataLayerDescriptor> GeorefMetadataLayerDescriptor::create(
70
            Dataset& dataset,
71
            const std::string& name,
72
            GeorefMetadataProfile profile,
73
            DataType keyType,
74
            RecordDefinition definition,
75
            uint64_t chunkSize,
76
            int compressionLevel)
77
0
{
78
0
    return std::shared_ptr<GeorefMetadataLayerDescriptor>(
79
0
        new GeorefMetadataLayerDescriptor{dataset, name, profile, keyType,
80
0
                                          std::move(definition), chunkSize, compressionLevel});
81
0
}
82
83
//! Open an existing georeferenced metadata layer descriptor.
84
/*!
85
\param dataset
86
    The BAG Dataset this layer belongs to.
87
\param name
88
    The name of the simple layer this layer has metadata for.
89
90
\return
91
    The existing georeferenced metadata layer descriptor.
92
*/
93
std::shared_ptr<GeorefMetadataLayerDescriptor> GeorefMetadataLayerDescriptor::open(
94
    Dataset& dataset,
95
    const std::string& name)
96
72
{
97
72
    const auto& h5file = dataset.getH5file();
98
99
72
    const std::string internalPath{GEOREF_METADATA_PATH + name + COMPOUND_KEYS};
100
72
    const auto h5dataSet = ::H5::DataSet{h5file.openDataSet(internalPath)};
101
102
    // Determine keyType.
103
72
    const auto fileDataType = h5dataSet.getDataType();
104
105
72
    DataType keyType = DT_UNKNOWN_DATA_TYPE;
106
72
    switch(fileDataType.getSize())
107
72
    {
108
0
    case 1:
109
0
        keyType = DT_UINT8;
110
0
        break;
111
64
    case 2:
112
64
        keyType = DT_UINT16;
113
64
        break;
114
0
    case 4:
115
0
        keyType = DT_UINT32;
116
0
        break;
117
0
    case 8:
118
0
        keyType = DT_UINT64;
119
0
        break;
120
2
    default:
121
2
        throw InvalidKeyType{};
122
72
    }
123
124
    // Determine Record Definition.
125
64
    const auto attribute = h5dataSet.openAttribute(COMPOUND_RECORD_DEFINITION);
126
127
64
    const auto fileDataSpace = attribute.getSpace();
128
129
64
    const auto numDims = fileDataSpace.getSimpleExtentNdims();
130
64
    if (numDims != 1)
131
0
        throw InvalidValueSize{};
132
133
64
    hsize_t numFields = 0;
134
64
    fileDataSpace.getSimpleExtentDims(&numFields, nullptr);
135
136
64
    RecordDefinition definition(numFields);
137
138
64
    attribute.read(attribute.getDataType(), definition.data());
139
140
    // Determine chunk size and compression level.
141
64
    const auto chunkSize = BAG::getChunkSize(h5file, internalPath);
142
64
    const auto compressionLevel = BAG::getCompressionLevel(h5file, internalPath);
143
144
    // Read metadata profile as string from HDF5 file attribute and convert to GeorefMetadataProfile enum value.
145
64
    std::string profileString;
146
64
    if (h5dataSet.attrExists(METADATA_PROFILE_TYPE)) {
147
45
        const auto metadataProfileAtt = h5dataSet.openAttribute(METADATA_PROFILE_TYPE);
148
45
        metadataProfileAtt.read(metadataProfileAtt.getDataType(), profileString);
149
45
    } else {
150
19
        std::cerr << "Unable to find georeferenced metadata layer attribute '" << METADATA_PROFILE_TYPE <<
151
19
                  "' for simple layer '" << name << "', setting profile to '" << UNKOWN_METADATA_PROFILE_NAME <<
152
19
                  "'." << std::endl;
153
19
        profileString = UNKOWN_METADATA_PROFILE_NAME;
154
19
    }
155
156
64
    GeorefMetadataProfile profile;
157
64
    auto search = BAG::kStringMapGeorefMetadataProfile.find(profileString);
158
64
    if (search != BAG::kStringMapGeorefMetadataProfile.end()) {
159
        // This is a recognized metadata profile (either a specific known profile or the unknown profile)
160
11
        profile = search->second;
161
53
    } else {
162
53
        std::cerr << "WARNING: Unrecognized georeferenced metadata layer metadata profile '" << profileString <<
163
53
                  "' for simple layer '" << name << "', assuming value was '" << UNKOWN_METADATA_PROFILE_NAME <<
164
53
                  "'." << std::endl;
165
53
        profile = UNKNOWN_METADATA_PROFILE;
166
53
    }
167
168
64
    return std::shared_ptr<GeorefMetadataLayerDescriptor>(
169
64
        new GeorefMetadataLayerDescriptor{dataset, name, profile, keyType, definition,
170
64
                                          chunkSize, compressionLevel});
171
64
}
172
173
174
//! \copydoc LayerDescriptor::getDataType
175
DataType GeorefMetadataLayerDescriptor::getDataTypeProxy() const noexcept
176
4
{
177
4
    return m_keyType;
178
4
}
179
180
//! Retrieve the BAG Dataset this layer belongs to.
181
/*!
182
\return
183
    The BAG Dataset.
184
*/
185
std::weak_ptr<Dataset> GeorefMetadataLayerDescriptor::getDataset() const &
186
0
{
187
0
    return m_pBagDataset;
188
0
}
189
190
//! \copydoc LayerDescriptor::getElementSize
191
uint8_t GeorefMetadataLayerDescriptor::getElementSizeProxy() const noexcept
192
4
{
193
4
    return m_elementSize;
194
4
}
195
196
//! Retrieve the definition of a record/value.
197
/*!
198
\return
199
    The definition of a record/value.
200
*/
201
const RecordDefinition&
202
GeorefMetadataLayerDescriptor::getDefinition() const & noexcept
203
42
{
204
42
    return m_definition;
205
42
}
206
207
//! Retrieve the metadata profile type.
208
/*!
209
\return
210
    The metadata profile type.
211
 */
212
0
GeorefMetadataProfile GeorefMetadataLayerDescriptor::getProfile() {
213
0
    return m_profile;
214
0
}
215
216
}  // namespace BAG
217