Coverage Report

Created: 2026-06-28 07:10

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