Skip to content

Commit cf80fcf

Browse files
committed
add static open function that auto-detects the Zarr version
1 parent bf4a1ea commit cf80fcf

File tree

11 files changed

+251
-84
lines changed

11 files changed

+251
-84
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package dev.zarr.zarrjava.core;
2+
3+
import dev.zarr.zarrjava.store.StoreHandle;
4+
5+
import javax.annotation.Nonnull;
6+
7+
public class AbstractNode implements Node {
8+
9+
@Nonnull
10+
public final StoreHandle storeHandle;
11+
12+
protected AbstractNode(@Nonnull StoreHandle storeHandle) {
13+
this.storeHandle = storeHandle;
14+
}
15+
}

src/main/java/dev/zarr/zarrjava/core/Array.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010

1111
import javax.annotation.Nonnull;
1212
import javax.annotation.Nullable;
13+
import java.io.IOException;
1314
import java.nio.ByteBuffer;
1415
import java.util.Arrays;
1516
import java.util.stream.Stream;
1617

17-
public abstract class Array extends Node {
18+
public abstract class Array extends AbstractNode {
1819

1920
protected CodecPipeline codecPipeline;
2021
protected abstract ArrayMetadata metadata();
@@ -23,6 +24,28 @@ protected Array(StoreHandle storeHandle) throws ZarrException {
2324
super(storeHandle);
2425
}
2526

27+
/**
28+
* Opens an existing Zarr array at a specified storage location. Automatically detects the Zarr version.
29+
*
30+
* @param storeHandle the storage location of the Zarr array
31+
* @throws IOException throws IOException if the metadata cannot be read
32+
* @throws ZarrException throws ZarrException if the Zarr array cannot be opened
33+
*/
34+
public static Array open(StoreHandle storeHandle) throws IOException, ZarrException {
35+
boolean isV3 = storeHandle.resolve(ZARR_JSON).exists();
36+
boolean isV2 = storeHandle.resolve(ZARRAY).exists();
37+
if (isV3 && isV2) {
38+
throw new ZarrException("Both Zarr v2 and v3 arrays found at the specified location.");
39+
} else if (isV3) {
40+
return dev.zarr.zarrjava.v3.Array.open(storeHandle);
41+
} else if (isV2) {
42+
return dev.zarr.zarrjava.v2.Array.open(storeHandle);
43+
} else {
44+
throw new ZarrException("No Zarr array found at the specified location.");
45+
}
46+
}
47+
48+
2649
/**
2750
* Writes a ucar.ma2.Array into the Zarr array at a specified offset. The shape of the Zarr array
2851
* needs be large enough for the write.
Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,61 @@
11
package dev.zarr.zarrjava.core;
2+
23
import dev.zarr.zarrjava.ZarrException;
34
import dev.zarr.zarrjava.store.StoreHandle;
45

56
import javax.annotation.Nonnull;
67
import javax.annotation.Nullable;
8+
import java.io.IOException;
79
import java.util.Objects;
810
import java.util.stream.Stream;
911

10-
public abstract class Group extends Node {
11-
12-
protected Group(@Nonnull StoreHandle storeHandle) {
13-
super(storeHandle);
14-
}
15-
16-
@Nullable
17-
public abstract Node get(String key) throws ZarrException;
18-
19-
public Stream<Node> list() {
20-
return storeHandle.list()
21-
.map(key -> {
22-
try {
23-
return get(key);
24-
} catch (ZarrException e) {
25-
throw new RuntimeException(e);
26-
}
27-
})
28-
.filter(Objects::nonNull);
29-
}
30-
31-
public Node[] listAsArray() {
32-
try (Stream<Node> nodeStream = list()) {
33-
return nodeStream.toArray(Node[]::new);
12+
public abstract class Group extends AbstractNode {
13+
14+
protected Group(@Nonnull StoreHandle storeHandle) {
15+
super(storeHandle);
16+
}
17+
18+
19+
/**
20+
* Opens an existing Zarr group at a specified storage location. Automatically detects the Zarr version.
21+
*
22+
* @param storeHandle the storage location of the Zarr group
23+
* @throws IOException throws IOException if the metadata cannot be read
24+
* @throws ZarrException throws ZarrException if the Zarr group cannot be opened
25+
*/
26+
public static Group open(StoreHandle storeHandle) throws IOException, ZarrException {
27+
boolean isV3 = storeHandle.resolve(ZARR_JSON).exists();
28+
boolean isV2 = storeHandle.resolve(ZGROUP).exists();
29+
if (isV3 && isV2) {
30+
throw new ZarrException("Both Zarr v2 and v3 groups found at " + storeHandle);
31+
} else if (isV3) {
32+
return dev.zarr.zarrjava.v3.Group.open(storeHandle);
33+
} else if (isV2) {
34+
return dev.zarr.zarrjava.v2.Group.open(storeHandle);
35+
} else {
36+
throw new ZarrException("No Zarr group found at " + storeHandle);
37+
}
38+
}
39+
40+
41+
@Nullable
42+
public abstract Node get(String key) throws ZarrException;
43+
44+
public Stream<Node> list() {
45+
return storeHandle.list()
46+
.map(key -> {
47+
try {
48+
return get(key);
49+
} catch (ZarrException e) {
50+
throw new RuntimeException(e);
51+
}
52+
})
53+
.filter(Objects::nonNull);
54+
}
55+
56+
public Node[] listAsArray() {
57+
try (Stream<Node> nodeStream = list()) {
58+
return nodeStream.toArray(Node[]::new);
59+
}
3460
}
35-
}
3661
}
Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,37 @@
11
package dev.zarr.zarrjava.core;
22

3+
import dev.zarr.zarrjava.ZarrException;
34
import dev.zarr.zarrjava.store.StoreHandle;
4-
import javax.annotation.Nonnull;
55

6-
public abstract class Node {
6+
import java.io.IOException;
7+
import java.nio.file.NoSuchFileException;
78

8-
@Nonnull
9-
public final StoreHandle storeHandle;
9+
public interface Node {
1010

11-
protected Node(@Nonnull StoreHandle storeHandle) {
12-
this.storeHandle = storeHandle;
13-
}
11+
String ZARR_JSON = "zarr.json";
12+
String ZARRAY = ".zarray";
13+
String ZGROUP = ".zgroup";
1414

15+
/**
16+
* Opens an existing Zarr array or group at a specified storage location. Automatically detects the Zarr version.
17+
*
18+
* @param storeHandle the storage location of the Zarr array
19+
* @throws IOException throws IOException if the metadata cannot be read
20+
* @throws ZarrException throws ZarrException if the Zarr array cannot be opened
21+
*/
22+
static Node open(StoreHandle storeHandle) throws IOException, ZarrException {
23+
boolean isV3 = storeHandle.resolve(ZARR_JSON).exists();
24+
boolean isV2 = storeHandle.resolve(ZARRAY).exists() || storeHandle.resolve(ZGROUP).exists();
25+
26+
if (isV3 && isV2) {
27+
throw new ZarrException("Both Zarr v2 and v3 nodes found at " + storeHandle);
28+
} else if (isV3) {
29+
return dev.zarr.zarrjava.v3.Node.open(storeHandle);
30+
} else if (isV2) {
31+
return dev.zarr.zarrjava.v2.Node.open(storeHandle);
32+
} else {
33+
throw new NoSuchFileException("No Zarr node found at " + storeHandle);
34+
}
35+
}
1536
}
37+

src/main/java/dev/zarr/zarrjava/v2/Group.java

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,29 +43,13 @@ public static Group create(
4343
}
4444

4545
@Nullable
46-
public dev.zarr.zarrjava.core.Node get(String key) throws ZarrException {
46+
public Node get(String key) throws ZarrException {
4747
StoreHandle keyHandle = storeHandle.resolve(key);
48-
ObjectMapper objectMapper = makeObjectMapper();
49-
boolean isGroup = keyHandle.resolve(ZGROUP).exists();
50-
boolean isArray = keyHandle.resolve(ZARRAY).exists();
51-
if (isGroup && isArray) {
52-
throw new ZarrException("Key '" + key + "' contains both a .zgroup and a .zarray file.");
53-
} else if (isGroup) {
54-
try {
55-
return new Group(keyHandle, objectMapper.readValue(
56-
Utils.toArray(keyHandle.resolve(ZGROUP).readNonNull()), GroupMetadata.class));
57-
} catch (IOException e) {
48+
try {
49+
return Node.open(keyHandle);
50+
} catch (IOException e) {
5851
return null;
59-
}
60-
} else if (isArray) {
61-
try {
62-
return new dev.zarr.zarrjava.v2.Array(keyHandle, objectMapper.readValue(
63-
Utils.toArray(keyHandle.resolve(ZARRAY).readNonNull()), ArrayMetadata.class));
64-
} catch (IOException e) {
65-
throw new ZarrException("Failed to read array metadata for key '" + key + "'.", e);
66-
}
6752
}
68-
return null;
6953
}
7054

7155
public Group createGroup(String key, GroupMetadata groupMetadata)

src/main/java/dev/zarr/zarrjava/v2/Node.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
5+
import dev.zarr.zarrjava.ZarrException;
6+
import dev.zarr.zarrjava.store.StoreHandle;
57
import dev.zarr.zarrjava.v2.codec.CodecRegistry;
68

7-
public interface Node {
8-
String ZARRAY = ".zarray";
9-
String ZGROUP = ".zgroup";
9+
import java.io.IOException;
10+
import java.nio.file.NoSuchFileException;
11+
12+
public interface Node extends dev.zarr.zarrjava.core.Node {
1013

1114
static ObjectMapper makeObjectMapper() {
1215
ObjectMapper objectMapper = new ObjectMapper();
@@ -15,4 +18,28 @@ static ObjectMapper makeObjectMapper() {
1518
return objectMapper;
1619
}
1720

21+
/**
22+
* Opens an existing Zarr array or group at a specified storage location.
23+
*
24+
* @param storeHandle the storage location of the Zarr array
25+
* @throws IOException throws IOException if the metadata cannot be read
26+
* @throws ZarrException throws ZarrException if the Zarr array or group cannot be opened
27+
*/
28+
static Node open(StoreHandle storeHandle) throws IOException, ZarrException {
29+
boolean isGroup = storeHandle.resolve(ZGROUP).exists();
30+
boolean isArray = storeHandle.resolve(ZARRAY).exists();
31+
32+
if (isGroup && isArray) {
33+
throw new ZarrException("Store handle '" + storeHandle + "' contains both a " + ZGROUP + " and a " + ZARRAY + " file.");
34+
} else if (isGroup) {
35+
return Group.open(storeHandle);
36+
} else if (isArray) {
37+
try {
38+
return Array.open(storeHandle);
39+
} catch (IOException e) {
40+
throw new ZarrException("Failed to read array metadata for store handle '" + storeHandle + "'.", e);
41+
}
42+
}
43+
throw new NoSuchFileException("Store handle '" + storeHandle + "' does not contain a " + ZGROUP + " or a " + ZARRAY + " file.");
44+
}
1845
}

src/main/java/dev/zarr/zarrjava/v3/Group.java

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -51,29 +51,10 @@ public static Group create(@Nonnull StoreHandle storeHandle) throws IOException,
5151
}
5252

5353
@Nullable
54-
public dev.zarr.zarrjava.core.Node get(String key) throws ZarrException {
54+
public Node get(String key) throws ZarrException {
5555
StoreHandle keyHandle = storeHandle.resolve(key);
56-
ObjectMapper objectMapper = makeObjectMapper();
57-
ByteBuffer metadataBytes = keyHandle.resolve(ZARR_JSON)
58-
.read();
59-
if (metadataBytes == null) {
60-
return null;
61-
}
62-
byte[] metadataBytearray = Utils.toArray(metadataBytes);
6356
try {
64-
String nodeType = objectMapper.readTree(metadataBytearray)
65-
.get("node_type")
66-
.asText();
67-
switch (nodeType) {
68-
case ArrayMetadata.NODE_TYPE:
69-
return new Array(keyHandle,
70-
objectMapper.readValue(metadataBytearray, ArrayMetadata.class));
71-
case GroupMetadata.NODE_TYPE:
72-
return new Group(keyHandle,
73-
objectMapper.readValue(metadataBytearray, GroupMetadata.class));
74-
default:
75-
throw new ZarrException("Unsupported node_type '" + nodeType + "' in " + keyHandle);
76-
}
57+
return Node.open(keyHandle);
7758
} catch (IOException e) {
7859
return null;
7960
}

src/main/java/dev/zarr/zarrjava/v3/GroupMetadata.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
import java.util.Map;
88
import javax.annotation.Nullable;
99

10-
public final class GroupMetadata {
10+
public final class GroupMetadata extends dev.zarr.zarrjava.core.GroupMetadata {
1111

1212
static final String NODE_TYPE = "group";
1313
static final int ZARR_FORMAT = 3;
1414
@JsonProperty("zarr_format")
15-
public final int zarrFormat = 3;
15+
public final int zarrFormat = ZARR_FORMAT;
1616
@JsonProperty("node_type")
1717
public final String nodeType = "group";
1818

src/main/java/dev/zarr/zarrjava/v3/Node.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@
22

33
import com.fasterxml.jackson.databind.ObjectMapper;
44
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
5+
import dev.zarr.zarrjava.ZarrException;
6+
import dev.zarr.zarrjava.store.StoreHandle;
7+
import dev.zarr.zarrjava.utils.Utils;
58
import dev.zarr.zarrjava.v3.codec.CodecRegistry;
69

7-
public interface Node {
8-
String ZARR_JSON = "zarr.json";
10+
import java.io.IOException;
11+
import java.nio.ByteBuffer;
12+
13+
14+
public interface Node extends dev.zarr.zarrjava.core.Node{
915

1016
static ObjectMapper makeObjectMapper() {
1117
ObjectMapper objectMapper = new ObjectMapper();
@@ -14,4 +20,29 @@ static ObjectMapper makeObjectMapper() {
1420
return objectMapper;
1521
}
1622

23+
/**
24+
* Opens an existing Zarr array or group at a specified storage location.
25+
*
26+
* @param storeHandle the storage location of the Zarr array or group
27+
* @throws IOException throws IOException if the metadata cannot be read
28+
* @throws ZarrException throws ZarrException if the Zarr array or group cannot be opened
29+
*/
30+
static Node open(StoreHandle storeHandle) throws IOException, ZarrException {
31+
ObjectMapper objectMapper = makeObjectMapper();
32+
ByteBuffer metadataBytes = storeHandle.resolve(ZARR_JSON).readNonNull();
33+
byte[] metadataBytearray = Utils.toArray(metadataBytes);
34+
String nodeType = objectMapper.readTree(metadataBytearray)
35+
.get("node_type")
36+
.asText();
37+
switch (nodeType) {
38+
case ArrayMetadata.NODE_TYPE:
39+
return new Array(storeHandle,
40+
objectMapper.readValue(metadataBytearray, ArrayMetadata.class));
41+
case GroupMetadata.NODE_TYPE:
42+
return new Group(storeHandle,
43+
objectMapper.readValue(metadataBytearray, GroupMetadata.class));
44+
default:
45+
throw new ZarrException("Unsupported node_type '" + nodeType + "' at " + storeHandle);
46+
}
47+
}
1748
}

src/main/java/dev/zarr/zarrjava/v3/codec/Codec.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@
77
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "name")
88
public interface Codec extends dev.zarr.zarrjava.core.codec.Codec {
99
long computeEncodedSize(long inputByteLength, ArrayMetadata.CoreArrayMetadata arrayMetadata) throws ZarrException;
10-
}
11-
10+
}

0 commit comments

Comments
 (0)