Skip to content

Commit ad29062

Browse files
authored
Merge branch 'main' into accept-missing-configuration-for-chunkKeyEncoding
2 parents 51e700f + 2b959d3 commit ad29062

File tree

11 files changed

+553
-53
lines changed

11 files changed

+553
-53
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ public static Group open(String path) throws IOException, ZarrException {
6464
}
6565

6666
@Nullable
67-
public abstract Node get(String key) throws ZarrException;
67+
public abstract Node get(String key) throws ZarrException, IOException;
6868

6969
public Stream<Node> list() {
7070
return storeHandle.list()
7171
.map(key -> {
7272
try {
7373
return get(key);
74-
} catch (ZarrException e) {
74+
} catch (Exception e) {
7575
throw new RuntimeException(e);
7676
}
7777
})
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package dev.zarr.zarrjava.store;
2+
3+
import javax.annotation.Nonnull;
4+
import javax.annotation.Nullable;
5+
import java.nio.ByteBuffer;
6+
import java.util.*;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
import java.util.stream.Stream;
9+
10+
public class MemoryStore implements Store, Store.ListableStore {
11+
private final Map<List<String>, byte[]> map = new ConcurrentHashMap<>();
12+
13+
List<String> resolveKeys(String[] keys) {
14+
ArrayList<String> resolvedKeys = new ArrayList<>();
15+
for(String key:keys){
16+
if(key.startsWith("/")){
17+
key = key.substring(1);
18+
}
19+
resolvedKeys.addAll(Arrays.asList(key.split("/")));
20+
}
21+
return resolvedKeys;
22+
}
23+
24+
@Override
25+
public boolean exists(String[] keys) {
26+
return map.containsKey(resolveKeys(keys));
27+
}
28+
29+
@Nullable
30+
@Override
31+
public ByteBuffer get(String[] keys) {
32+
return get(keys, 0);
33+
}
34+
35+
@Nullable
36+
@Override
37+
public ByteBuffer get(String[] keys, long start) {
38+
return get(keys, start, -1);
39+
}
40+
41+
@Nullable
42+
@Override
43+
public ByteBuffer get(String[] keys, long start, long end) {
44+
byte[] bytes = map.get(resolveKeys(keys));
45+
if (bytes == null) return null;
46+
if (end < 0) end = bytes.length;
47+
if (end > Integer.MAX_VALUE) throw new IllegalArgumentException("End index too large");
48+
return ByteBuffer.wrap(bytes, (int) start, (int) end);
49+
}
50+
51+
52+
@Override
53+
public void set(String[] keys, ByteBuffer bytes) {
54+
map.put(resolveKeys(keys), bytes.array());
55+
}
56+
57+
@Override
58+
public void delete(String[] keys) {
59+
map.remove(resolveKeys(keys));
60+
}
61+
62+
public Stream<String> list(String[] keys) {
63+
List<String> prefix = resolveKeys(keys);
64+
Set<String> allKeys = new HashSet<>();
65+
66+
for (List<String> k : map.keySet()) {
67+
if (k.size() <= prefix.size() || ! k.subList(0, prefix.size()).equals(prefix))
68+
continue;
69+
for (int i = 0; i < k.size(); i++) {
70+
List<String> subKey = k.subList(0, i+1);
71+
allKeys.add(String.join("/", subKey));
72+
}
73+
}
74+
return allKeys.stream();
75+
}
76+
77+
@Nonnull
78+
@Override
79+
public StoreHandle resolve(String... keys) {
80+
return new StoreHandle(this, keys);
81+
}
82+
83+
@Override
84+
public String toString() {
85+
return String.format("<MemoryStore {%s}>", hashCode());
86+
}
87+
}
88+

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import dev.zarr.zarrjava.ZarrException;
66
import dev.zarr.zarrjava.core.Attributes;
77
import dev.zarr.zarrjava.store.FilesystemStore;
8+
import dev.zarr.zarrjava.store.MemoryStore;
89
import dev.zarr.zarrjava.store.StoreHandle;
910
import dev.zarr.zarrjava.utils.Utils;
1011
import dev.zarr.zarrjava.core.codec.CodecPipeline;
@@ -87,6 +88,16 @@ public static Array open(String path) throws IOException, ZarrException {
8788
return open(Paths.get(path));
8889
}
8990

91+
/**
92+
* Creates a new Zarr array with the provided metadata in an in-memory store
93+
*
94+
* @param arrayMetadata the metadata of the Zarr array
95+
* @throws IOException if the metadata cannot be serialized
96+
* @throws ZarrException if the Zarr array cannot be created
97+
*/
98+
public static Array create(ArrayMetadata arrayMetadata) throws ZarrException, IOException {
99+
return create(new StoreHandle(new MemoryStore()), arrayMetadata);
100+
}
90101
/**
91102
* Creates a new Zarr array with the provided metadata at a specified storage location. This
92103
* method will raise an exception if a Zarr array already exists at the specified storage

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

Lines changed: 166 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
import dev.zarr.zarrjava.ZarrException;
66
import dev.zarr.zarrjava.core.Attributes;
77
import dev.zarr.zarrjava.store.FilesystemStore;
8+
import dev.zarr.zarrjava.store.MemoryStore;
89
import dev.zarr.zarrjava.store.StoreHandle;
910
import dev.zarr.zarrjava.utils.Utils;
1011

1112
import javax.annotation.Nonnull;
1213
import javax.annotation.Nullable;
1314
import java.io.IOException;
1415
import java.nio.ByteBuffer;
16+
import java.nio.file.NoSuchFileException;
1517
import java.nio.file.Path;
1618
import java.nio.file.Paths;
1719
import java.util.function.Function;
@@ -26,6 +28,12 @@ protected Group(@Nonnull StoreHandle storeHandle, @Nonnull GroupMetadata groupMe
2628
this.metadata = groupMetadata;
2729
}
2830

31+
/**
32+
* Opens an existing Zarr group at a specified storage location.
33+
*
34+
* @param storeHandle the storage location of the Zarr group
35+
* @throws IOException if the metadata cannot be read
36+
*/
2937
public static Group open(@Nonnull StoreHandle storeHandle) throws IOException {
3038
ObjectMapper mapper = makeObjectMapper();
3139
GroupMetadata metadata = mapper.readValue(
@@ -40,77 +48,221 @@ public static Group open(@Nonnull StoreHandle storeHandle) throws IOException {
4048
return new Group(storeHandle, metadata);
4149
}
4250

51+
/**
52+
* Opens an existing Zarr group at a specified storage location.
53+
*
54+
* @param path the storage location of the Zarr group
55+
* @throws IOException if the metadata cannot be read
56+
*/
4357
public static Group open(Path path) throws IOException {
4458
return open(new StoreHandle(new FilesystemStore(path)));
4559
}
4660

47-
public static Group open(String path) throws IOException {
61+
/**
62+
* Opens an existing Zarr group at a specified storage location.
63+
*
64+
* @param path the storage location of the Zarr group
65+
* @throws IOException if the metadata cannot be read
66+
*/
67+
public static Group open(String path) throws IOException {
4868
return open(Paths.get(path));
4969
}
5070

71+
/**
72+
* Creates a new Zarr group with the provided metadata in an in-memory store.
73+
*
74+
* @param groupMetadata the metadata of the Zarr group
75+
* @throws IOException if the metadata cannot be serialized
76+
*/
77+
public static Group create(@Nonnull GroupMetadata groupMetadata) throws IOException {
78+
return new Group(new MemoryStore().resolve(), groupMetadata).writeMetadata();
79+
}
80+
81+
/**
82+
* Creates a new Zarr group with the provided metadata at a specified storage location.
83+
*
84+
* @param storeHandle the storage location of the Zarr group
85+
* @param groupMetadata the metadata of the Zarr group
86+
* @throws IOException if the metadata cannot be serialized
87+
*/
5188
public static Group create(
5289
@Nonnull StoreHandle storeHandle, @Nonnull GroupMetadata groupMetadata
5390
) throws IOException {
54-
ObjectWriter objectWriter = makeObjectWriter();
55-
ByteBuffer metadataBytes = ByteBuffer.wrap(objectWriter.writeValueAsBytes(groupMetadata));
56-
storeHandle.resolve(ZGROUP).set(metadataBytes);
57-
if (groupMetadata.attributes != null) {
58-
StoreHandle attrsHandle = storeHandle.resolve(ZATTRS);
59-
ByteBuffer attrsBytes = ByteBuffer.wrap(
60-
objectWriter.writeValueAsBytes(groupMetadata.attributes));
61-
attrsHandle.set(attrsBytes);
62-
}
63-
return new Group(storeHandle, groupMetadata);
91+
return new Group(storeHandle, groupMetadata).writeMetadata();
6492
}
6593

94+
/**
95+
* Creates a new Zarr group with default metadata at a specified storage location.
96+
*
97+
* @param storeHandle the storage location of the Zarr group
98+
* @throws IOException if the metadata cannot be serialized
99+
* @throws ZarrException if the metadata is invalid
100+
*/
66101
public static Group create(@Nonnull StoreHandle storeHandle) throws IOException, ZarrException {
67102
return create(storeHandle, new GroupMetadata());
68103
}
69104

105+
/**
106+
* Creates a new Zarr group with the provided attributes at a specified storage location.
107+
*
108+
* @param storeHandle the storage location of the Zarr group
109+
* @param attributes the attributes of the Zarr group
110+
* @throws IOException if the metadata cannot be serialized
111+
* @throws ZarrException if the attributes are invalid
112+
*/
70113
public static Group create(@Nonnull StoreHandle storeHandle, Attributes attributes) throws IOException, ZarrException {
71114
return create(storeHandle, new GroupMetadata(attributes));
72115
}
73116

117+
/**
118+
* Creates a new Zarr group with default metadata at a specified storage location.
119+
*
120+
* @param path the storage location of the Zarr group
121+
* @throws IOException if the metadata cannot be serialized
122+
* @throws ZarrException if the metadata is invalid
123+
*/
74124
public static Group create(Path path) throws IOException, ZarrException {
75125
return create(new StoreHandle(new FilesystemStore(path)));
76126
}
77127

128+
/**
129+
* Creates a new Zarr group with the provided attributes at a specified storage location.
130+
*
131+
* @param path the storage location of the Zarr group
132+
* @param attributes the attributes of the Zarr group
133+
* @throws IOException if the metadata cannot be serialized
134+
* @throws ZarrException if the attributes are invalid
135+
*/
78136
public static Group create(Path path, Attributes attributes) throws IOException, ZarrException {
79137
return create(new StoreHandle(new FilesystemStore(path)), attributes);
80138
}
81139

140+
/**
141+
* Creates a new Zarr group with default metadata at a specified storage location.
142+
*
143+
* @param path the storage location of the Zarr group
144+
* @throws IOException if the metadata cannot be serialized
145+
* @throws ZarrException if the metadata is invalid
146+
*/
82147
public static Group create(String path) throws IOException, ZarrException {
83148
return create(Paths.get(path));
84149
}
85150

151+
/**
152+
* Creates a new Zarr group with the provided attributes at a specified storage location.
153+
*
154+
* @param path the storage location of the Zarr group
155+
* @param attributes the attributes of the Zarr group
156+
* @throws IOException if the metadata cannot be serialized
157+
* @throws ZarrException if the attributes are invalid
158+
*/
86159
public static Group create(String path, Attributes attributes) throws IOException, ZarrException {
87160
return create(Paths.get(path), attributes);
88161
}
89162

163+
/**
164+
* Retrieves a node (group or array) at the specified key within the current group.
165+
*
166+
* @param key the key of the node to retrieve
167+
* @return the node at the specified key, or null if it does not exist
168+
* @throws ZarrException if the node cannot be opened
169+
* @throws IOException if there is an error accessing the storage
170+
*/
90171
@Nullable
91-
public Node get(String key) throws ZarrException {
172+
public Node get(String key) throws ZarrException, IOException {
92173
StoreHandle keyHandle = storeHandle.resolve(key);
93174
try {
94175
return Node.open(keyHandle);
95-
} catch (IOException e) {
176+
} catch (NoSuchFileException e) {
96177
return null;
97178
}
98179
}
99180

181+
/**
182+
* Creates a new subgroup with default metadata at the specified key.
183+
*
184+
* @param key the key of the new Zarr group within the current group
185+
* @return the created subgroup
186+
* @throws IOException if the metadata cannot be serialized
187+
* @throws ZarrException if the group cannot be created
188+
*/
100189
public Group createGroup(String key) throws IOException, ZarrException {
101190
return Group.create(storeHandle.resolve(key));
102191
}
103192

193+
/**
194+
* Creates a new array with the provided metadata at the specified key.
195+
*
196+
* @param key the key of the new Zarr array within the current group
197+
* @param arrayMetadata the metadata of the Zarr array
198+
* @return the created array
199+
* @throws IOException if the metadata cannot be serialized
200+
* @throws ZarrException if the array cannot be created
201+
*/
104202
public Array createArray(String key, ArrayMetadata arrayMetadata)
105203
throws IOException, ZarrException {
106204
return Array.create(storeHandle.resolve(key), arrayMetadata);
107205
}
108206

207+
/**
208+
* Creates a new array with the provided metadata at the specified key.
209+
*
210+
* @param key the key of the new Zarr array within the current group
211+
* @param arrayMetadataBuilderMapper a function that modifies the array metadata
212+
* @return the created array
213+
* @throws IOException if the metadata cannot be serialized
214+
* @throws ZarrException if the array cannot be created
215+
*/
109216
public Array createArray(String key, Function<ArrayMetadataBuilder, ArrayMetadataBuilder> arrayMetadataBuilderMapper)
110-
throws IOException, ZarrException {
217+
throws IOException, ZarrException {
111218
return Array.create(storeHandle.resolve(key), arrayMetadataBuilderMapper, false);
112219
}
113220

221+
private Group writeMetadata() throws IOException {
222+
return writeMetadata(this.metadata);
223+
}
224+
225+
private Group writeMetadata(GroupMetadata newGroupMetadata) throws IOException {
226+
ObjectWriter objectWriter = makeObjectWriter();
227+
ByteBuffer metadataBytes = ByteBuffer.wrap(objectWriter.writeValueAsBytes(newGroupMetadata));
228+
storeHandle.resolve(ZGROUP).set(metadataBytes);
229+
if (newGroupMetadata.attributes != null) {
230+
StoreHandle attrsHandle = storeHandle.resolve(ZATTRS);
231+
ByteBuffer attrsBytes = ByteBuffer.wrap(
232+
objectWriter.writeValueAsBytes(newGroupMetadata.attributes));
233+
attrsHandle.set(attrsBytes);
234+
}
235+
this.metadata = newGroupMetadata;
236+
return this;
237+
}
238+
239+
/**
240+
* Sets new attributes for the group, replacing any existing attributes.
241+
*
242+
* @param newAttributes the new attributes to set
243+
* @return the updated group
244+
* @throws ZarrException if the new attributes are invalid
245+
* @throws IOException if the metadata cannot be serialized
246+
*/
247+
public Group setAttributes(Attributes newAttributes) throws ZarrException, IOException {
248+
GroupMetadata newGroupMetadata = new GroupMetadata(newAttributes);
249+
return writeMetadata(newGroupMetadata);
250+
}
251+
252+
/**
253+
* Updates the attributes of the group using a mapper function.
254+
*
255+
* @param attributeMapper a function that takes the current attributes and returns the updated attributes
256+
* @return the updated group
257+
* @throws ZarrException if the new attributes are invalid
258+
* @throws IOException if the metadata cannot be serialized
259+
*/
260+
public Group updateAttributes(Function<Attributes, Attributes> attributeMapper)
261+
throws ZarrException, IOException {
262+
return setAttributes(attributeMapper.apply(metadata.attributes));
263+
}
264+
265+
114266
@Override
115267
public String toString() {
116268
return String.format("<v2.Group {%s}>", storeHandle);

0 commit comments

Comments
 (0)