Skip to content

Commit 187061f

Browse files
committed
New test for h5ex_t attributes.
1 parent 31b6853 commit 187061f

22 files changed

Lines changed: 581 additions & 104 deletions

.gitignore

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,5 @@ build/
3838
/*.h5
3939
hdf5/*/*.h5
4040
/bouml/
41-
/src/main/resources/h5ex_t/h5ex_t_array.h5
42-
/src/main/resources/h5ex_t/h5ex_t_bit.h5
43-
/src/main/resources/h5ex_t/h5ex_t_cmpd.h5
44-
/src/main/resources/h5ex_t/h5ex_t_commit.h5
45-
/src/main/resources/h5ex_t/h5ex_t_cpxcmpd.h5
46-
/src/main/resources/h5ex_t/h5ex_t_enum.h5
47-
/src/main/resources/h5ex_t/h5ex_t_float.h5
48-
/src/main/resources/h5ex_t/h5ex_t_int.h5
49-
/src/main/resources/h5ex_t/h5ex_t_objref.h5
50-
/src/main/resources/h5ex_t/h5ex_t_opaque.h5
51-
/src/main/resources/h5ex_t/h5ex_t_regref.h5
52-
/src/main/resources/h5ex_t/h5ex_t_string.h5
53-
/src/main/resources/h5ex_t/h5ex_t_vlen.h5
54-
/src/main/resources/h5ex_t/h5ex_t_vlstring.h5
41+
/src/main/resources/h5ex_t/*.h5
42+
/src/main/resources/h5ex_t/att/*.h5

src/main/java/org/hdf5javalib/examples/HDF5Examples/ArrayAttributeRead.java

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.nio.file.StandardOpenOption;
1313
import java.util.Arrays;
1414

15+
import static org.hdf5javalib.utils.HdfDisplayUtils.displayAttributes;
1516
import static org.hdf5javalib.utils.HdfReadUtils.getResourcePath;
1617

1718
/**
@@ -44,24 +45,12 @@ private void run() {
4445
try (SeekableByteChannel channel = Files.newByteChannel(filePath, StandardOpenOption.READ)) {
4546
HdfFileReader reader = new HdfFileReader(channel).readFile();
4647
log.debug("BTree: {} ", reader.getBTree().getRoot());
47-
// try (HdfDataset dataSet = reader.getRootGroup().getDataset("/DS1").orElseThrow()) {
48-
// displayData(channel, dataSet, reader);
49-
// }
5048
for (HdfDataset dataSet : reader.getDatasets()) {
51-
// displayData(channel, dataSet, reader);
5249
displayAttributes(dataSet);
5350
}
5451
}
5552
} catch (Exception e) {
5653
throw new RuntimeException(e);
5754
}
5855
}
59-
60-
private void displayAttributes(HdfDataset dataSet) {
61-
dataSet.getAttributeMessages().forEach(message -> {
62-
HdfDataHolder dataHolder = message.getHdfDataHolder();
63-
HdfData[] data = dataHolder.getAll(HdfData[].class);
64-
System.out.println("Data = " + Arrays.toString(data));
65-
});
66-
}
6756
}

src/main/java/org/hdf5javalib/examples/HDF5Examples/ExamplesRead.java

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.nio.file.StandardOpenOption;
1414

1515
import static org.hdf5javalib.utils.HdfDisplayUtils.displayData;
16+
import static org.hdf5javalib.utils.HdfDisplayUtils.displayFile;
1617

1718
/**
1819
* Demonstrates reading and processing compound data from an HDF5 file.
@@ -49,22 +50,9 @@ private void run() {
4950
System.out.println("Running " + p.getFileName());
5051
displayFile(p);
5152
});
52-
} catch (URISyntaxException e) {
53-
throw new RuntimeException(e);
54-
} catch (IOException e) {
53+
} catch (URISyntaxException | IOException e) {
5554
throw new RuntimeException(e);
5655
}
5756
}
5857

59-
public void displayFile(Path filePath) {
60-
try (SeekableByteChannel channel = Files.newByteChannel(filePath, StandardOpenOption.READ)) {
61-
HdfFileReader reader = new HdfFileReader(channel).readFile();
62-
for (HdfDataset dataSet : reader.getDatasets()) {
63-
log.info("{} ", dataSet);
64-
displayData(channel, dataSet, reader);
65-
}
66-
} catch (Exception e) {
67-
log.error("Exception in displayFile: {}", filePath, e);
68-
}
69-
}
7058
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.hdf5javalib.examples.h5ex_t.att;
2+
3+
import org.hdf5javalib.datasource.TypedDataSource;
4+
5+
import java.io.IOException;
6+
import java.net.URISyntaxException;
7+
import java.nio.file.Files;
8+
import java.nio.file.Path;
9+
import java.nio.file.Paths;
10+
import java.util.Objects;
11+
import java.util.stream.Stream;
12+
13+
import static org.hdf5javalib.utils.HdfDisplayUtils.displayFileAttr;
14+
15+
/**
16+
* Demonstrates reading and processing compound data from an HDF5 file.
17+
* <p>
18+
* The {@code CompoundRead} class serves as an example application that reads
19+
* a compound dataset from an HDF5 file, processes it using a {@link TypedDataSource},
20+
* and displays the results. It showcases filtering and mapping operations on the
21+
* dataset, as well as conversion to a custom Java class.
22+
* </p>
23+
*/
24+
public class h5ex_t_att_read {
25+
/**
26+
* Entry point for the application.
27+
*
28+
* @param args command-line arguments (not used)
29+
*/
30+
public static void main(String[] args) {
31+
new h5ex_t_att_read().run();
32+
}
33+
34+
/**
35+
* Executes the main logic of reading and displaying compound data from an HDF5 file.
36+
*/
37+
private void run() {
38+
try {
39+
// List all .h5 files in HDF5Examples resources directory
40+
Path dirPath = Paths.get(Objects.requireNonNull(h5ex_t_att_read.class.getClassLoader().getResource("h5ex_t/att")).toURI());
41+
try ( Stream<Path> streamList = Files.list(dirPath) ) {
42+
streamList.filter(p -> p.toString().endsWith(".h5"))
43+
.forEach(p -> {
44+
System.out.println("Running " + p.getFileName());
45+
displayFileAttr(p);
46+
});
47+
48+
}
49+
} catch (URISyntaxException | IOException e) {
50+
throw new RuntimeException(e);
51+
}
52+
}
53+
54+
}
Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
package org.hdf5javalib.examples.h5ex_t;
22

33
import org.hdf5javalib.datasource.TypedDataSource;
4-
import org.hdf5javalib.hdfjava.HdfDataset;
5-
import org.hdf5javalib.hdfjava.HdfFileReader;
64

75
import java.io.IOException;
86
import java.net.URISyntaxException;
9-
import java.nio.channels.SeekableByteChannel;
107
import java.nio.file.Files;
118
import java.nio.file.Path;
129
import java.nio.file.Paths;
13-
import java.nio.file.StandardOpenOption;
10+
import java.util.Objects;
11+
import java.util.stream.Stream;
1412

15-
import static org.hdf5javalib.utils.HdfDisplayUtils.displayData;
13+
import static org.hdf5javalib.utils.HdfDisplayUtils.displayFile;
1614

1715
/**
1816
* Demonstrates reading and processing compound data from an HDF5 file.
@@ -24,8 +22,6 @@
2422
* </p>
2523
*/
2624
public class h5ex_t_read {
27-
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(h5ex_t_read.class);
28-
2925
/**
3026
* Entry point for the application.
3127
*
@@ -40,31 +36,19 @@ public static void main(String[] args) {
4036
*/
4137
private void run() {
4238
try {
43-
4439
// List all .h5 files in HDF5Examples resources directory
45-
Path dirPath = Paths.get(h5ex_t_read.class.getClassLoader().getResource("h5ex_t").toURI());
46-
Files.list(dirPath)
47-
.filter(p -> p.toString().endsWith(".h5"))
48-
.forEach(p -> {
49-
System.out.println("Running " + p.getFileName());
50-
displayFile(p);
51-
});
52-
} catch (URISyntaxException e) {
53-
throw new RuntimeException(e);
54-
} catch (IOException e) {
55-
throw new RuntimeException(e);
56-
}
57-
}
40+
Path dirPath = Paths.get(Objects.requireNonNull(h5ex_t_read.class.getClassLoader().getResource("h5ex_t")).toURI());
41+
try ( Stream<Path> streamList = Files.list(dirPath) ) {
42+
streamList.filter(p -> p.toString().endsWith(".h5"))
43+
.forEach(p -> {
44+
System.out.println("Running " + p.getFileName());
45+
displayFile(p);
46+
});
5847

59-
public void displayFile(Path filePath) {
60-
try (SeekableByteChannel channel = Files.newByteChannel(filePath, StandardOpenOption.READ)) {
61-
HdfFileReader reader = new HdfFileReader(channel).readFile();
62-
for (HdfDataset dataSet : reader.getDatasets()) {
63-
log.info("{} ", dataSet);
64-
displayData(channel, dataSet, reader);
6548
}
66-
} catch (Exception e) {
67-
log.error("Exception in displayFile: {}", filePath, e);
49+
} catch (URISyntaxException | IOException e) {
50+
throw new RuntimeException(e);
6851
}
6952
}
53+
7054
}

src/main/java/org/hdf5javalib/hdffile/dataobjects/messages/AttributeMessage.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,4 +253,8 @@ public HdfDataHolder getHdfDataHolder() {
253253
return hdfDataHolder;
254254
}
255255

256+
public HdfString getName() {
257+
return name;
258+
}
259+
256260
}

src/main/java/org/hdf5javalib/utils/HdfDataHolder.java

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -213,30 +213,60 @@ public <T> T getAll(Class<T> clazz) {
213213
}
214214

215215
if (isScalar()) {
216-
// Check if the requested type is assignable from our scalar's type.
217-
if (clazz.isAssignableFrom(singleInstance.getClass())) {
218-
return clazz.cast(singleInstance);
219-
} else {
220-
throw new IllegalArgumentException(String.format(
221-
"Type mismatch: Requested class '%s' is not compatible with the scalar content of type '%s'.",
222-
clazz.getCanonicalName(),
223-
singleInstance.getClass().getCanonicalName()
224-
));
225-
}
216+
return singleInstance.getInstance(clazz);
226217
} else { // isArray()
227-
// Check if the requested type is assignable from our array's type.
228-
if (clazz.isAssignableFrom(array.getClass())) {
229-
return clazz.cast(array);
230-
} else {
231-
throw new IllegalArgumentException(String.format(
232-
"Type mismatch: Requested array type '%s' is not compatible with the actual array type '%s'.",
233-
clazz.getCanonicalName(),
234-
array.getClass().getCanonicalName()
235-
));
236-
}
218+
return createAndConvertArray(clazz, array, dimensionality, dimensions);
219+
}
220+
}
221+
222+
// Assuming this is inside your HdfDataHolder or similar class
223+
private <T> T createAndConvertArray(Class<T> clazz, Object sourceArray, int dimensionality, int[] dimensions) {
224+
// Compute the array depth and base type from clazz
225+
Class<?> baseType = clazz;
226+
int depth = 0;
227+
while (baseType.isArray()) {
228+
baseType = baseType.getComponentType();
229+
depth++;
230+
}
231+
if (depth != dimensionality) {
232+
throw new IllegalArgumentException("Dimensionality mismatch: clazz has depth " + depth + " but expected " + dimensionality);
233+
}
234+
235+
// Create the new multi-dimensional array
236+
Object targetArray = Array.newInstance(baseType, dimensions);
237+
238+
// If no source to convert from, return the empty array
239+
if (sourceArray == null) {
240+
return clazz.cast(targetArray);
237241
}
242+
243+
// Fill the target array by converting from source (recursive)
244+
fillArray(targetArray, sourceArray, baseType, 0, dimensions);
245+
246+
return clazz.cast(targetArray);
238247
}
239248

249+
// Recursive helper to fill the target array
250+
private void fillArray(Object target, Object source, Class<?> baseType, int dimIndex, int[] dimensions) {
251+
if (dimIndex == dimensions.length - 1) {
252+
// Leaf level: convert and set elements
253+
int len = dimensions[dimIndex];
254+
Object[] src = (Object[]) source; // e.g., HdfData[]
255+
for (int i = 0; i < len; i++) {
256+
HdfData hdfData = (HdfData) src[i];
257+
Object value = hdfData.getInstance(baseType);
258+
Array.set(target, i, value);
259+
}
260+
} else {
261+
// Intermediate level: recurse into sub-arrays
262+
int len = dimensions[dimIndex];
263+
Object[] src = (Object[]) source;
264+
for (int i = 0; i < len; i++) {
265+
Object childTarget = Array.get(target, i);
266+
fillArray(childTarget, src[i], baseType, dimIndex + 1, dimensions);
267+
}
268+
}
269+
}
240270

241271
/**
242272
* Returns an iterator that traverses all HdfData elements in a flattened, sequential order.

src/main/java/org/hdf5javalib/utils/HdfDisplayUtils.java

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@
1010

1111
import java.io.IOException;
1212
import java.nio.channels.SeekableByteChannel;
13+
import java.nio.file.Files;
14+
import java.nio.file.Path;
15+
import java.nio.file.StandardOpenOption;
1316
import java.util.Arrays;
17+
import java.util.function.Supplier;
1418
import java.util.stream.Collectors;
1519

1620
/**
@@ -23,21 +27,48 @@
2327
* </p>
2428
*/
2529
public class HdfDisplayUtils {
26-
private static Logger log = LoggerFactory.getLogger(HdfDisplayUtils.class);
27-
/**
28-
* Creates a version attribute for a dataset.
29-
* <p>
30-
* Adds a "GIT root revision" attribute to the specified dataset with a predefined
31-
* value containing revision and URL information.
32-
* </p>
33-
*
34-
* @param hdfDataFile the HDF5 file context
35-
* @param dataset the dataset to which the attribute is added
36-
*/
37-
public static void writeVersionAttribute(HdfDataFile hdfDataFile, HdfDataset dataset) {
38-
String ATTRIBUTE_NAME = "GIT root revision";
39-
String ATTRIBUTE_VALUE = "Revision: , URL: ";
40-
dataset.createAttribute(ATTRIBUTE_NAME, ATTRIBUTE_VALUE, hdfDataFile);
30+
private static final Logger log = LoggerFactory.getLogger(HdfDisplayUtils.class);
31+
32+
// Define a functional interface for actions that may need channel, dataset, and reader
33+
@FunctionalInterface
34+
interface FileAction {
35+
void perform(SeekableByteChannel channel, HdfDataset dataSet, HdfFileReader reader) throws Exception;
36+
}
37+
38+
// Generalized method to process the file and apply a custom action per dataset
39+
private static void processFile(Path filePath, FileAction action) {
40+
try (SeekableByteChannel channel = Files.newByteChannel(filePath, StandardOpenOption.READ)) {
41+
HdfFileReader reader = new HdfFileReader(channel).readFile();
42+
for (HdfDataset dataSet : reader.getDatasets()) {
43+
log.info("{} ", dataSet);
44+
action.perform(channel, dataSet, reader);
45+
}
46+
} catch (Exception e) {
47+
log.error("Exception in processFile: {}", filePath, e);
48+
}
49+
}
50+
51+
public static void displayFileAttr(Path filePath) {
52+
processFile(filePath, (channel, dataSet, reader) -> displayAttributes(dataSet));
53+
}
54+
55+
public static void displayFile(Path filePath) {
56+
processFile(filePath, (channel, dataSet, reader) -> displayData(channel, dataSet, reader));
57+
}
58+
59+
public static void displayAttributes(HdfDataset dataSet) {
60+
dataSet.getAttributeMessages().forEach(message -> {
61+
HdfDataHolder dataHolder = message.getHdfDataHolder();
62+
if (dataHolder.getDimensionality() == 1) {
63+
HdfData[] data = dataHolder.getAll(HdfData[].class);
64+
System.out.println("Data = " + Arrays.toString(data));
65+
} else if (dataHolder.getDimensionality() == 2) {
66+
HdfData[][] data = dataHolder.getAll(HdfData[][].class);
67+
for ( HdfData[] row : data) {
68+
System.out.println("Row = " + Arrays.toString(row));
69+
}
70+
}
71+
});
4172
}
4273

4374
public static void displayData(SeekableByteChannel channel, HdfDataset ds, HdfFileReader reader) throws Exception {

0 commit comments

Comments
 (0)